import axios, { type AxiosInstance } from 'axios';
import cache from '@/utils/cache';
import notify from '@/utils/notify';
import i18n from '@/i18n';
import type { TokenResultDto } from '@/models/authorize';

const axiosInstance: AxiosInstance = axios.create({});

//http request 拦截器
axiosInstance.interceptors.request.use(
    config => {
        //加载语言选项
        const culture: string = cache.getLocale();
        if (config.url) {
            config.url += (config.url.indexOf('?') > 0 ? '&' : '?') + 'culture=' + culture;
        }
        //console.log(config.url);

        //判断路由是否为无需登录路由，如果是无需登录路由，无需继续下去
        if (window.location.pathname === '/login') {
            return config;
        }

        const token: TokenResultDto | null = cache.getToken();
        //判断是否存在token，不存在跳转登录
        if (!token) {
            window.location.replace('/login');
            return config;
        }

        //判断过期时间(单位/秒)，如果离过期还有20秒钟，执行刷新token
        if ((token.expiresIn * 1000 - new Date().getTime()) <= 20 * 1000) {
            config.headers['X-Authorization'] = 'Bearer ' + token.refreshToken;
        }
        config.headers.Authorization = 'Bearer ' + token.accessToken;
        return config;
    },
    error => {
        return Promise.reject(error);
    }
);

//http response 拦截器
axiosInstance.interceptors.response.use(
    response => {
        const data = response.data;
        if (data && data.statusCode && typeof (data.statusCode) === 'number') {
            const expiresIn: number = response.headers['expires-in'] ? Number.parseInt(response.headers['expires-in']) : 0;
            const token: TokenResultDto = {
                accessToken: response.headers['access-token'],
                refreshToken: response.headers['x-access-token'],
                expiresIn: expiresIn
            };
            if (token.accessToken && token.refreshToken && token.expiresIn > 0) {
                cache.setToken(token);
            }
            let errorMessage: string = '';
            switch (data.statusCode) {
                case 200:
                case 204:
                    break;
                case 500:
                    let message: string = i18n.global.t('https.500');
                    if (data.errors && data.errors !== 'An internal error occurred during your request!') {
                        message = data.errors;
                    }
                    errorMessage = message;
                    break;
                case 400:
                    const errors = Object.values(data.errors);
                    for (let i: number = 0; i < errors.length; i++) {
                        const error = errors[i] as [];
                        if (error.length > 0) {
                            errorMessage += error;
                            break;
                        }
                    }
                    break;
            }
            if (errorMessage) {
                notify.error(errorMessage);
                return Promise.reject({ response: response });
            }
        }
        return response;
    },
    error => {
        let errorMessage: string = i18n.global.t('https.505');
        if (error.response) {
            switch (error.response.status) {
                case 401:
                    window.location.replace('/login');
                    return Promise.reject(error);
                case 403:
                    errorMessage = i18n.global.t('https.403');
                    break;
                case 404:
                    errorMessage = i18n.global.t('https.404');
                    break;
            }
        }
        notify.error(errorMessage);
        return Promise.reject(error)
    }
)

export default axiosInstance 